package com.coocaa.typhoon.api.v1.milvus.service;

import cn.hutool.crypto.SecureUtil;
import com.coocaa.cirrus.common.base.util.BeanConvertUtil;
import com.coocaa.cirrus.common.base.util.RetryUtil;
import com.coocaa.typhoon.api.v1.milvus.constant.MilvusConstant;
import com.coocaa.typhoon.api.v1.milvus.model.UserFileMilvusDTO;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.DeleteReq;
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.request.UpsertReq;
import io.milvus.v2.service.vector.response.DeleteResp;
import io.milvus.v2.service.vector.response.QueryResp;
import io.milvus.v2.service.vector.response.UpsertResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author bijiahao
 * @date : 2025/9/25 11:09
 * @description
 */
@Slf4j
@Service
public class UserFileMilvusUpdateService {

    @Autowired
    private MilvusClientV2 client;

    private static String getFilterByUserId(String userId) {
        return "user_id == '" + userId + "'";
    }

    public <T> T queryById(String collectionName, Long id, Class<T> clazz) {
        List<String> cols = BeanConvertUtil.getColumnNames(clazz);
        QueryResp.QueryResult queryResult = queryById(collectionName, id, cols);
        if (null == queryResult) {
            return null;
        }
        return BeanConvertUtil.convertMapToEntity(queryResult.getEntity(), clazz);
    }

    public QueryResp.QueryResult queryById(String collectionName, Long id, List<String> cols) {
        try {
            QueryReq queryReq = QueryReq.builder()
                    .collectionName(collectionName)
                    .ids(Collections.singletonList(id))
                    .outputFields(cols)
                    .limit(1)
                    .build();
            QueryResp getResp = client.query(queryReq);
            if (null == getResp) {
                return null;
            }
            List<QueryResp.QueryResult> results = getResp.getQueryResults();
            return CollectionUtils.isNotEmpty(results) ? results.get(0) : null;
        } catch (Exception e) {
           return null;
        }
    }

    public <T> T queryByUserId(String collectionName, String userId, Class<T> clazz) {
        List<String> cols = BeanConvertUtil.getColumnNames(clazz);
        QueryResp.QueryResult queryResult = queryOne(collectionName, userId, cols);
        if (null == queryResult) {
            return null;
        }
        return BeanConvertUtil.convertMapToEntity(queryResult.getEntity(), clazz);
    }

    public QueryResp.QueryResult queryOne(String collectionName, String userId, List<String> cols) {
        QueryReq queryReq = QueryReq.builder()
                .collectionName(collectionName)
                .filter(getFilterByUserId(userId))
                .outputFields(cols)
                .limit(1)
                .build();
        QueryResp getResp = client.query(queryReq);
        List<QueryResp.QueryResult> results = getResp.getQueryResults();
        return CollectionUtils.isNotEmpty(results) ? results.get(0) : null;
    }

    public void delete(String collectionName, String userId) {
        DeleteReq deleteReq = DeleteReq.builder()
                .collectionName(collectionName)
                .filter(getFilterByUserId(userId))
                .build();
        DeleteResp deleteResp = RetryUtil.callWithThrow(userId, () -> client.delete(deleteReq), 3, 1000);
        log.info("deleteResp:{}", deleteResp.getDeleteCnt());
    }


    public void update(String collectionName, Object entity) {
        update(collectionName, BeanConvertUtil.buildDataByObj(entity));
    }

    public void updateBatch(List<UserFileMilvusDTO> updateList) {
        if (CollectionUtils.isEmpty(updateList)) {
            return;
        }
        int size = updateList.size();
        int limitSize = 1000;
        if (size > limitSize) {
            int splitCount = size / limitSize;
            int lastCount = size - limitSize * splitCount;
            int index = 0;
            for (; index < splitCount; index++) {
                List<UserFileMilvusDTO> sub = updateList.subList(index * limitSize, limitSize * (index + 1));
                List<JsonObject> data = BeanConvertUtil.buildData(sub);
                update(MilvusConstant.USER_FILE, data);
            }
            if (lastCount > 0) {
                List<UserFileMilvusDTO> last = updateList.subList(splitCount * limitSize, size);
                List<JsonObject> data = BeanConvertUtil.buildData(last);
                update(MilvusConstant.USER_FILE, data);
            }
        } else {
            List<JsonObject> data = BeanConvertUtil.buildData(updateList);
            update(MilvusConstant.USER_FILE, data);
        }

    }

    public void update(String collectionName, List<JsonObject> data) {
        UpsertReq upsertReq = UpsertReq.builder()
                .collectionName(collectionName)
                .data(data)
                .build();
        Gson gson = BeanConvertUtil.getGson();
        final String key = SecureUtil.md5(gson.toJson(data));
        UpsertResp upsertResp = RetryUtil.callWithThrow(key, () -> client.upsert(upsertReq), 3, 1000);
        log.info("upsertResp:{}", upsertResp.getUpsertCnt());
    }
}
